/*
 * This file is part of the Sx Framework Library.
 * 
 * Copyright (C) 2013 University of Colorado Denver
 * <min.choi@ucdenver.edu> <shane.transue@ucdenver.edu>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
 * copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in 
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 * DEALINGS IN THE SOFTWARE.
 */
#ifndef SX_INTERSECTIONS_H
#define SX_INTERSECTIONS_H

#include <sxMath.h>

namespace Sx {
namespace Math {
namespace Intersections {

/*
 * This function determines if the provided segment intersects the provided
 * triangle formed by three points, that is, triangle_p0, triangle_p1, and
 * triangle_p2 define the three points of the triangle that is tested. The line
 * segment is provided as a set of two endpoints.
 *
 *  segment_p0 - Represents the first endpoint of the line segment
 *  segment_p1 - Represents the second endpoint of the line segment
 *  triangle_p0 - Represents the first point that forms the triangle
 *  triangle_p1 - Represents the second point that forms the triangle
 *  triangle_p2 - Represents the third point that forms the triangle
 *  point - If there is an intersection between the provided line segment and
 *	        the triangle then the exact location of that intersection is
 *          stored in the provided point reference
 *
 * This function returns true if the provided line segment intersects the
 * triangle formed from the three provided points; otherwise this function
 * returns false when there is no intersection.
 */
bool SegmentIntersectTrianglef(const Eigen::Vector3f& segment_p0, const Eigen::Vector3f& segmnet_p1, const Eigen::Vector3f& triangle_p0, const Eigen::Vector3f& triangle_p1, const Eigen::Vector3f& triangle_p2, Eigen::Vector3f& point);
bool SegmentIntersectTriangled(const Eigen::Vector3d& segment_p0, const Eigen::Vector3d& segmnet_p1, const Eigen::Vector3d& triangle_p0, const Eigen::Vector3d& triangle_p1, const Eigen::Vector3d& triangle_p2, Eigen::Vector3d& point);

/*
 * This function determines if the provided line segment intersects 
 * an axis aligned bounding box. The line segment is provided as a
 * pair of endpoints. The axis aligned bounding box is provided as
 * a min and max vector set. These are the values of the opposing
 * corners of the axis aligned bounding box where min is the values
 * down the -x, -y, and -z axes. Max is the value set down the positive
 * x, y, and z axes.
 *
 *  min - Represents the minimum extents of the axis aligned bounding box
 *  max - Represents the maximum extents of the axis aligned bounding box
 *  segment_p0 - The first endpoint of the line segment
 *  segment_p1 - The second endpoint of the line segment
 *  point - If there is an intersection between the provided line segment
 * and the axis aligned bounding box defined by min and max, then the exact
 * intersection point is stored in the point reference.
 *
 * If there is an intersection between the provided line segment and axis
 * aligned bounding box then this function returns true; otherwise this
 * function returns false, indicating that there was no intersection.
 */
bool SegmentIntersectAxisAlignedBoundingBox(const Eigen::Vector3f& min, const Eigen::Vector3f& max, const Eigen::Vector3f& segment_p0, const Eigen::Vector3f& segment_p1, Eigen::Vector3f& point);

/*
 * This function determines if there is an intersection between the provided
 * line segment and the sphere defined by its center and radius.
 *
 *  segment_p0 - The first endpoint of the line segment
 *  segment_p1 - The second endpoint of the line segment
 *  center - This point represents the center of the sphere
 *  radius - The radius of the sphere
 *  point - If there is an intersection between the provided line segment
 *          and the defined sphere, then the exact intersection point
 *          is stored in the provided point reference.
 *
 * This function returns true if there is an intersection between the
 * provided line segment and the sphere defined by its center and its
 * radius. Otherwise this function returns false, indicating that there
 * was no intersection.
 */
bool SegmentIntersectSphere(const Eigen::Vector3f& segment_p0, const Eigen::Vector3f& segment_p1, const Eigen::Vector3f& center, float radius, Eigen::Vector3f& point);

/*
 * This function returns true if the provided point is in the provided plane
 * (defined by the normal). If the point is on the same side as the normal
 * then the function will set onSameSideAsNormal to true; otherwise the point
 * is on the opposite side of the plane and this function will set
 * onSameSideAsNormal to false.
 */
bool PointInPlane(const Eigen::Vector3d& planeNormal, const Eigen::Vector3d& point, bool& onSameSideAsNormal);
bool PointInPlane(const Eigen::Vector3d& planeNormal, const Eigen::Vector3d& point, bool& onSameSideAsNormal, float threshold);

}

}

}

#endif
